import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class ReflectClassDemo {
    // 在这个类里面反射 Main里面所定义的Student
    public static void reflectNewInstance(){
        // 第一步还是需要有一个Class对象
        try {
            Class<?> c1 = Class.forName("Student");
            // 这样使用
          Constructor<?> constructor = c1.getDeclaredConstructor(String.class,int.class); // 这个可以获取所有的构造方法

            // 下面这一行由程序员来决定 是否要去调用它，传入一个参数true
            constructor.setAccessible(true); // 必须要写它 ，就像一个开关一样

            //接下来开始调用
            Student student1 = null;
            try {
                student1 = (Student) constructor.newInstance("gg",19);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            System.out.println(student1);

            try {
             Student student = (Student) c1.newInstance(); // 这个同时也需要抛异常
                // 接下来就可以直接输出了
                System.out.println("学生对象:" +student); //
            } catch (InstantiationException e) {
                throw new RuntimeException(e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        }
    }
    public static void reflectPrivateConstructor() {
        try {
            Class<?> classStudent = Class.forName("Student");
            //注意传入对应的参数
            Constructor<?> declaredConstructorStudent = classStudent.getDeclaredConstructor(String.class,int.class);
            //Constructor<?> declaredConstructorStudent = classStudent.getConstructor();
            //设置为true后可修改访问权限
            declaredConstructorStudent.setAccessible(true);
            Object objectStudent = declaredConstructorStudent.newInstance("高博",15);
            //Object objectStudent = declaredConstructorStudent.newInstance();
            Student student = (Student) objectStudent;
            System.out.println("获得私有构造哈数且修改姓名和年龄："+student);
        }catch (InvocationTargetException e) {
            throw new RuntimeException(e);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException(e);
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        } catch (InstantiationException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }

    // 反射私有属性
    public static void reflectPrivateField() {
        try {
            Class<?> classStudent = Class.forName("Student");

            Field field  = classStudent.getDeclaredField("name");
            field.setAccessible(true);
            //可以修改该属性的值
            Student student = (Student)classStudent.newInstance();

            field.set(student,"小明"); //这个方法可以改这个filed

           // String name = (String) field.get(student);
            System.out.println("反射私有属性修改了name："+ student);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    // 反射私有方法
    public static void reflectPrivateMethod() {
        try {
            Class<?> classStudent = Class.forName("Student");
            Method methodStudent = classStudent.getDeclaredMethod("function",String.class);
            System.out.println("私有方法的方法名为："+methodStudent.getName());
            //私有的一般都要加
            methodStudent.setAccessible(true);
            Object objectStudent = classStudent.newInstance();
            Student student = (Student) objectStudent;
            methodStudent.invoke(student,"我是给私有的function函数传的参数");

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    public static void main(String[] args) {
        // Class<?> c1 = Class.forName("Student"); 这中情况是使用最多的

        // 第一个 通过反射来创建对象
       // reflectNewInstance(); //这样就可以调用不带参数的对象了

       // reflectPrivateConstructor();
       // reflectPrivateField();
        reflectPrivateMethod();


    }
}
